package filesystem

import (
	"bufio"
	"os"
	"strings"
)

// GetFileLines 从文件中读取每行内容(省略空行,注意回车行也被忽略)
func GetFileLines(filePath string, ignoreBlank bool) (resultLines []string, err error) {
	var (
		file *os.File
	)
	resultLines = make([]string, 0)
	/*	os.Open() opens specific file in
		read-only mode and this return
		a pointer of type os.	*/

	if file, err = os.Open(filePath); err != nil {
		return
	}
	// The method os.File.Close() is called
	// on the os.File object to close the file
	defer file.Close()
	// The bufio.NewScanner() function is called in which the
	// object os.File passed as its parameter and this returns a
	// object bufio.Scanner which is further used on the
	// bufio.Scanner.Split() method.
	scanner := bufio.NewScanner(file)

	// The bufio.ScanLines is used as an
	// input to the method bufio.Scanner.Split()
	// and then the scanning forwards to each
	// new line using the bufio.Scanner.Scan()
	// method.
	scanner.Split(bufio.ScanLines)

	for scanner.Scan() {
		te := strings.TrimSpace(scanner.Text())
		if ignoreBlank && te == "" {
			continue
		}
		resultLines = append(resultLines, te)
	}

	return
}

// FindCommentContentFromGolangSourceFile
/*
	从golang源代码文件的注释搜索字符串
*/
func FindCommentContentFromGolangSourceFile(filePath string, searchString string) (docs map[int]string, err error) {
	var (
		file *os.File
	)
	if file, err = os.Open(filePath); err != nil {
		return
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	lineNumber := 1
	docs = make(map[int]string, 0)
	isCulveCommentBegin := false
	isCulveCommentEnd := true
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		//多行注释是否结束
		isCulveCommentEnd = strings.HasSuffix(line, "*/")
		if !isCulveCommentBegin {
			//没有多行注释开始标志,每行都检查是否开始
			isCulveCommentBegin = strings.HasPrefix(line, "/*")
		}
		if isCulveCommentBegin || strings.HasPrefix(line, "//") {
			if strings.Contains(line, searchString) {
				docs[lineNumber] = line
			}
		}
		if isCulveCommentEnd {
			//多行注释结束，意味着多行注释开始标志没有了
			isCulveCommentBegin = false
		}
		lineNumber++
	}

	err = scanner.Err()
	return
}

// FindCommentContentFromLinuxEtcHosts
/*
   从linux /etc/hosts文件的注释搜索字符串
   exceptSearchString: 例外搜索字符串，忽略包含例外搜索字符串的情况
*/
func FindCommentContentFromLinuxEtcHosts(filePath string, searchString string,
	exceptSearchString string) (maxLineNumber int, docs map[int]string, err error) {
	return FindContentFromLinuxEtcHosts(filePath, searchString, exceptSearchString, true)
}

// FindContentFromLinuxEtcHosts
/*
   从linux /etc/hosts文件的内容中搜索字符串
   exceptSearchString: 例外搜索字符串，忽略包含例外搜索字符串的情况
   isComment bool 表示是否从注释里面搜索
*/
func FindContentFromLinuxEtcHosts(filePath string, searchString string, exceptSearchString string,
	isComment bool) (maxLineNumber int, docs map[int]string, err error) {
	var (
		file *os.File
	)
	if file, err = os.Open(filePath); err != nil {
		return
	}
	defer file.Close()

	scanner := bufio.NewScanner(file)
	lineNumber := 1
	docs = make(map[int]string, 0)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		success := (isComment == strings.HasPrefix(line, "#")) && strings.Contains(line, searchString)
		if success && exceptSearchString != "" {
			//如果例外搜索字符串不是空白，忽略包含例外搜索字符串的情况
			success = !strings.Contains(line, exceptSearchString)
		}
		if success {
			docs[lineNumber] = line
			maxLineNumber = lineNumber
		}
		lineNumber++
	}

	err = scanner.Err()
	return
}
